\section{指针}
\begin{enumerate}
    \item int a：表示一个内存空间，这个空间用来存放一个整数（int）；
    \item int* a：表示一个内存空间，这个空间用来存放一个指针，这个指针指向一个存放整数的空间，即1中提到的空间；
    \item int** a：表示一个内存空间，这个空间用来存放一个指针，这个指针指向一个存放指针的空间，并且指向的这个空间中的指针，指向一个整数。也简单的说，指向了一个2中提到的空间,整个过程如\figref{fig:find_address}；
    \item int (*a)[10]：表示一个内存空间，这个空间用来存放一个指针，这个指针指向一个长度为10、类型为int的数组；和int** a的区别在于，++、+=1之后的结果不一样，其他用法基本相同。具体查看\figref{fig:array_address}
    \item int (*a)(int)：表示一个内存空间，这个空间用来存放一个指针，这个指针指向一个函数，这个函数有一个类型为int的参数，并且函数的返回类型也是int。
\end{enumerate}
\begin{figure}[!htbp]
    \centering
    \includegraphics[width=\textwidth]{find_address}
    \caption{寻址方法}
    \label{fig:find_address}
\end{figure}
\begin{figure}[!htbp]
    \centering
    \includegraphics[width=\textwidth]{array_address}
    \caption{数组与指针}
    \label{fig:array_address}
\end{figure}

\cppfile{code/pointer/test.c}
64bit Linux寻址空间图如\figref{fig:linux_memory}。
\begin{figure}[!htbp]
    \centering
    \includegraphics[width=\textwidth]{memory}
    \caption{内存空间分布}
    \label{fig:linux_memory}
\end{figure}

\begin{table}[!htbp]
    \caption{函数变量与地址}
    \begin{tabular}{p{0.2\textwidth}p{0.4\textwidth}p{0.4\textwidth}}
        \toprule
        变量            & 地址                               & 变量值                         \\
        \midrule
        a(main)         & (int *) 0x7fffffffda18             & 3                              \\
        b(main)         & (int *) 0x7fffffffda14             & 4                              \\
        pa(main)        & (int *) 0x7fffffffda18             & (int **) 0x7fffffffda08        \\
        pb(main)        & (int *) 0x7fffffffda14             & (int **) 0x7fffffffda00        \\
        global          & 0                                  & (int *) 0x601034 <global>      \\
        a(quadrate)     & (int *) 0x7fffffffd9cc             & 3                              \\
        a(rect)         & 0x7fffffffd9ac                     & 3                              \\
        count(rect)     & (int *) 0x601038 <rect.count>      & 1(++之后)                      \\
        count(quadrate) & (int *) 0x60103c <quadrate.count>  & 1                              \\
        s(rect)         & (int *) 0x7fffffffd9a4             & 26                             \\
        s(main)         & (int *) 0x7fffffffd9ec             & 9(main函数中quadrate返回)      \\
        pquadrate(main) & (int (*)(int)) 0x400510 <quadrate> & (int (**)(int)) 0x7fffffffd9f0 \\
        \bottomrule
    \end{tabular}
    \label{tab:var_add}
\end{table}
\begin{table}[!htbp]
    \caption{函数堆栈地址}
    \begin{tabular}{p{0.5\textwidth}p{0.5\textwidth}}
        \toprule
        函数     & 地址                                \\
        \midrule
        main     & (int (*)()) 0x400560 <main>         \\
        quadrate & (int (*)(int)) 0x400510 <quadrate>  \\
        rect     & (int (*)(int, int)) 0x4004d0 <rect> \\
        \bottomrule
    \end{tabular}
    \label{tab:func_stack}
\end{table}
\subsection{浅拷贝与深拷贝}
\subsection{左值引用与右值引用}
在C++11中所有的值必属于左值、右值两者之一，右值又可以细分为纯右值、将亡值。在C++11中可以取地址的、有名字的就是左值，反之，不能取地址的、没有名字的就是右值（将亡值或纯右值）。举个例子，int a = b+c, a 就是左值，其有变量名为a，通过\&a可以获取该变量的地址；表达式b+c、函数int func()的返回值是右值，在其被赋值给某一变量前，我们不能通过变量名找到它，\&(b+c)这样的操作则不会通过编译。

在理解C++11的右值前，先看看C++98中右值的概念：C++98中右值是纯右值，纯右值指的是临时变量值、不跟对象关联的字面量值。临时变量指的是非引用返回的函数返回值、表达式等，例如函数int func()的返回值，表达式a+b；不跟对象关联的字面量值，例如true，2，”C”等。

C++11对C++98中的右值进行了扩充。在C++11中右值又分为纯右值（prvalue，Pure Rvalue）和将亡值（xvalue，eXpiring Value）。其中纯右值的概念等同于我们在C++98标准中右值的概念，指的是临时变量和不跟对象关联的字面量值；将亡值则是C++11新增的跟右值引用相关的表达式，这样表达式通常是将要被移动的对象（移为他用），比如返回右值引用T\&\&的函数返回值、std::move的返回值，或者转换为T\&\&的类型转换函数的返回值。

将亡值可以理解为通过“盗取”其他变量内存空间的方式获取到的值。在确保其他变量不再被使用、或即将被销毁时，通过“盗取”的方式可以避免内存空间的释放和分配，能够延长变量值的生命期。

\subsubsection*{左值引用、右值引用}
左值引用就是对一个左值进行引用的类型。右值引用就是对一个右值进行引用的类型，事实上，由于右值通常不具有名字，我们也只能通过引用的方式找到它的存在。右值引用和左值引用都是属于引用类型。无论是声明一个左值引用还是右值引用，都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存，只是该对象的一个别名。左值引用是具名变量值的别名，而右值引用则是不具名（匿名）变量的别名。

左值引用通常也不能绑定到右值，但常量左值引用是个“万能”的引用类型。它可以接受非常量左值、常量左值、右值对其进行初始化。不过常量左值所引用的右值在它的“余生”中只能是只读的。相对地，非常量左值只能接受非常量左值对其进行初始化。
\begin{cpp}
    //int &a = 2; //cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
    int b = 2;
    const int &c = b;//常量左值引用绑定到非常量左值引用
    const int d = 2;//常量左值
    const int &e = c;//常量左值引用绑定到常量左值
    int f;
    //    int &&r1 = c;//右值引用绑定到左值常量引用，cannot bind rvalue reference of type ‘int&&’ to lvalue of type ‘const int’
    int &&r2 = std::move(f);
\end{cpp}
右值值引用通常不能绑定到任何的左值，要想绑定一个左值到右值引用，通常需要std::move()将左值强制转换为右值。
下\tabref{tab:lrref}列出了在C++11中各种引用类型可以引用的值的类型。值得注意的是，只要能够绑定右值的引用类型，都能够延长右值的生命期。
\begin{table}[H]
    \caption{左右值引用}
    \centering
    \begin{tabular}{cccccc}
        \multirow{2}{*}{引用类型} & \multicolumn{4}{c}{可以引用的值类型} & 注解                                                          \\
                                  & 非常量左值                           & 常量左值 & 非常量右值 & 常量右值 & 无                         \\
        非常量左值引用            & Y                                    & N        & N          & N        & 无                         \\
        常量左值引用              & Y                                    & Y        & Y          & Y        & 全能类型，可以用于拷贝语义 \\
        非常量右值引用            & N                                    & N        & Y          & N        & 用于移动语义，完美转化     \\
        常量右值引用              & N                                    & N        & Y          & Y        & 暂无用途
    \end{tabular}
    \label{tab:lrref}
\end{table}
